﻿/*
输入：
7 11
1 2 1
1 3 1
1 5 2
2 6 1
2 4 2
2 3 2
3 4 1
4 5 1
5 6 2
5 7 1
6 7 1
输出：
6
*/
// N个节点，K条边
string[] NKStr = Console.ReadLine().Split(" ");
int N = int.Parse(NKStr[0]);
int K = int.Parse(NKStr[1]);

// 构建图：邻接表
List<(int, int)>[] graph = new List<(int, int)>[N+1];
for (int i = 0; i <= N; i++)
{
    graph[i] = new List<(int, int)>();
}
for (int i = 0; i < K; i++)
{
    string[] stvStr = Console.ReadLine().Split(" ");
    int s = int.Parse(stvStr[0]);
    int t = int.Parse(stvStr[1]);
    int v = int.Parse(stvStr[2]);
    graph[s].Add((t, v));
    graph[t].Add((s, v));
}

// Prim算法找最小生成树
bool[] isInSet = new bool[N+1]; // 是否在集合中
int[] minDist = new int[N+1]; // 记录各个顶点到集合的最短距离
Array.Fill(minDist, int.MaxValue);
minDist[1] = 0;
for (int i = 1; i <= N; i++)
{
    // 1、找到离集合最近的顶点索引
    int index = 0;
    int min = int.MaxValue;
    for (int j = 1; j <= N; j++)
    {
        if(isInSet[j]) continue; // 已经在集合中
        if (min > minDist[j])
        {
            min = minDist[j];
            index = j;
        }
    }
    
    // 2、将顶点加入集合
    isInSet[index] = true;
    
    // 3、更新最近距离数组
    for (int j = 0; j < graph[index].Count; j++)
    {
        (int t, int v) = graph[index][j];
        if (isInSet[t]) continue;
        minDist[t] = v < minDist[t] ? v : minDist[t];
    }
}
Console.WriteLine(minDist[1..].Sum());